package com.lefevre.cms.service.redEnvelope.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lefevre.cms.bean.QueryResult;
import com.lefevre.cms.bean.payment.PaymentLog;
import com.lefevre.cms.bean.redEnvelope.GiveRedEnvelope;
import com.lefevre.cms.bean.redEnvelope.ReceiveRedEnvelope;
import com.lefevre.cms.mapper.GiveRedEnvelopeMapper;
import com.lefevre.cms.mapper.ReceiveRedEnvelopeMapper;
import com.lefevre.cms.service.besa.DaoSupport;
import com.lefevre.cms.service.redEnvelope.RedEnvelopeService;
import com.lefevre.cms.service.user.UserService;
import com.lefevre.cms.web.action.SystemException;
import com.lefevre.cms.web.action.payment.PaymentManage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.Query;
import java.math.BigDecimal;
import java.util.List;

/**
 * 红包管理实现类
 *
 * @author Lefevre
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RedEnvelopeServiceImpl extends DaoSupport<GiveRedEnvelope> implements RedEnvelopeService {
    private static final Logger logger = LoggerFactory.getLogger(RedEnvelopeServiceImpl.class);
    @Resource
    PaymentManage paymentManage;
    @Resource
    UserService userService;
    @Resource
    private GiveRedEnvelopeMapper giveRedEnvelopeMapper;
    @Resource
    private ReceiveRedEnvelopeMapper receiveRedEnvelopeMapper;

    /**
     * 根据Id查询发红包
     *
     * @param giveRedEnvelopeId
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public GiveRedEnvelope findById(String giveRedEnvelopeId) {
        return giveRedEnvelopeMapper.selectById(giveRedEnvelopeId);
    }


    /**
     * 保存发红包
     *
     * @param giveRedEnvelope 发红包
     * @param userName        用户名称
     * @param amount          扣减用户预存款
     * @param paymentLog      支付日志
     */
    public void saveGiveRedEnvelope(GiveRedEnvelope giveRedEnvelope, String userName, BigDecimal amount, PaymentLog paymentLog) {
        if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {//余额
            giveRedEnvelopeMapper.insert(giveRedEnvelope);

            paymentLog.setSourceParameterId(giveRedEnvelope.getId());
            Object paymentLogObject = paymentManage.createPaymentLogObject(paymentLog);
            //扣减用户预存款
            int i = userService.subtractUserDeposit(userName, amount, paymentLogObject);
            if (i == 0) {
                throw new SystemException("扣减预存款失败");
            }
        }
    }

    /**
     * 返还红包
     *
     * @param giveRedEnvelope  发红包
     * @param userName         用户名称
     * @param amount           返还用户金额
     * @param paymentLogObject 支付日志
     */
    public void refundRedEnvelope(GiveRedEnvelope giveRedEnvelope, String userName, BigDecimal amount, Object paymentLogObject) {
        //余额
        if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
            giveRedEnvelope.setRefundAmount(amount);
            int i = giveRedEnvelopeMapper.updateById(giveRedEnvelope);
            if (i > 0) {
                //扣减用户预存款
                int j = userService.addUserDeposit(userName, amount, paymentLogObject);
                if (j == 0) {
                    throw new SystemException("增加预存款失败");
                }
            } else {
                throw new SystemException("返还红包失败");
            }
        }
    }

    /**
     * 删除发红包
     *
     * @param userIdList 用户Id集合
     */
    public Integer deleteGiveRedEnvelope(List<Long> userIdList) {
        return giveRedEnvelopeMapper.delete(new LambdaUpdateWrapper<GiveRedEnvelope>().in(GiveRedEnvelope::getUserId, userIdList));
    }

    /**
     * 保存收红包
     * 先由redEnvelopeManage.createReceiveRedEnvelopeObject();方法生成对象再保存
     *
     * @param receiveRedEnvelope    收红包
     * @param giveRedEnvelopeId     发红包Id
     * @param grabRedEnvelopeUserId 抢到红包的用户Id
     */
    public int saveReceiveRedEnvelope(Object receiveRedEnvelope, String giveRedEnvelopeId, String grabRedEnvelopeUserId) {

        giveRedEnvelopeMapper.insert((GiveRedEnvelope) receiveRedEnvelope);

        Query query = em.createQuery("update GiveRedEnvelope o set o.grabRedEnvelopeUserIdGroup=CONCAT(o.grabRedEnvelopeUserIdGroup,?1)," +
                        " o.remainingQuantity=o.remainingQuantity-1, o.version=o.version+1 where o.id=?2 and o.remainingQuantity>0")
                .setParameter(1, grabRedEnvelopeUserId)
                .setParameter(2, giveRedEnvelopeId);
        return query.executeUpdate();
    }

    /**
     * 删除收红包
     *
     * @param userIdList 收红包用户Id集合
     */
    public Integer deleteReceiveRedEnvelope(List<Long> userIdList) {
        int i = 0;
        for (Long userId : userIdList) {
            i += this.deleteReceiveRedEnvelope(userId);
        }
        return i;
    }

    /**
     * 删除收红包
     *
     * @param userId 收红包用户Id
     */
    public Integer deleteReceiveRedEnvelope(Long userId) {
        return receiveRedEnvelopeMapper.delete(new LambdaUpdateWrapper<ReceiveRedEnvelope>().eq(ReceiveRedEnvelope::getReceiveUserId, userId));
    }

    /**
     * 拆红包
     *
     * @param receiveRedEnvelope 收红包Id
     * @param amount             红包金额
     * @param version            版本号
     * @param userName           拆红包的用户名称
     * @param paymentLogObject   支付日志
     */
    public Integer unwrapRedEnvelope(String receiveRedEnvelopeId, BigDecimal amount, Integer version, String userName, Object paymentLogObject) {
        ReceiveRedEnvelope receiveRedEnvelope = receiveRedEnvelopeMapper.selectOne(new LambdaQueryWrapper<ReceiveRedEnvelope>()
                .eq(ReceiveRedEnvelope::getId, receiveRedEnvelopeId)
                .eq(ReceiveRedEnvelope::getVersion, version));
        receiveRedEnvelope.setAmount(amount);

        int i = receiveRedEnvelopeMapper.updateById(receiveRedEnvelope);
        int j = 0;
        if (i > 0) {
            //增加用户预存款
            j = userService.addUserDeposit(userName, amount, paymentLogObject);
        }
        return j;
    }


    /**
     * 根据Id查询收红包
     *
     * @param receiveRedEnvelopeId 收红包Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public ReceiveRedEnvelope findByReceiveRedEnvelopeId(String receiveRedEnvelopeId) {
        return receiveRedEnvelopeMapper.selectById(receiveRedEnvelopeId);
    }


    /**
     * 根据用户Id查询收红包分页
     *
     * @param userId     用户Id
     * @param firstIndex 索引开始,即从哪条记录开始
     * @param maxResult  获取多少条数据
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<ReceiveRedEnvelope> findReceiveRedEnvelopeByUserId(Long userId, int firstIndex, int maxResult) {
        QueryResult<ReceiveRedEnvelope> qr = new QueryResult<>();

        LambdaQueryWrapper<ReceiveRedEnvelope> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReceiveRedEnvelope::getReceiveUserId, userId);
        wrapper.orderByDesc(ReceiveRedEnvelope::getReceiveTime);
        Page<ReceiveRedEnvelope> page = receiveRedEnvelopeMapper.selectPage(new Page<>(firstIndex, maxResult), wrapper);

        qr.setResultlist(page.getRecords());
        qr.setTotalrecord(page.getTotal());

        return qr;
    }
}
